﻿using System.Linq;
using SharpShare.Diagnostics;
using SharpShare.Storage;
using SharpShare.Storage.Security;

namespace SharpShare.Afp.Protocol.Handlers {
    internal class AfpCreateFileRequestHandler : IAfpRequestHandler {
        #region IAfpRequestHandler Members

        public byte CommandCode {
            get { return 7; }
        }

        public AfpResultCode Process(IAfpSession session, DsiHeader dsiHeader, AfpStream requestStream, AfpStream responseStream) {
            bool hardCreate = (requestStream.ReadUInt8() != 0);

            ushort volumeId = requestStream.ReadUInt16();
            uint directoryId = requestStream.ReadUInt32();
            var path = requestStream.ReadPath().ToList();
            IAfpVolume volume;
            IStorageContainer container = session.FindPath(path.Take(path.Count - 1), volumeId, directoryId, out volume).DemandContainer();

            StorageAccessList containerAccess = container.GetEffectiveAccess(session);

            containerAccess.DemandRight(StorageAccessRight.AddFiles);

            string fileName = path[path.Count - 1];

            containerAccess.DemandRight(StorageAccessRight.ListContents);

            IStorageItem existingItem = container.Contents[fileName];

            if (hardCreate) {
                // Hard create - means delete the file if it exists already.
                if (existingItem != null) {
                    if (existingItem.Is<IStorageContainer>()) {
                        // TODO: Documentation doesn't say what to do if attempting a hard create and a container exists with the same name.
                        return AfpResultCode.FPMiscErr;
                    }

                    containerAccess.DemandRight(StorageAccessRight.DeleteChild);
                    existingItem.GetEffectiveAccess(session).DemandRight(StorageAccessRight.Delete);
                    existingItem.Delete();
                }
            } else {
                if (existingItem != null) {
                    return AfpResultCode.FPObjectExists;
                }
            }

            IStorageFile newFile = container.CreateFile(fileName).DemandFile();

            if (session.User != null) {
                newFile.SetOwner(session.User.Id);
                newFile.SetGroup(session.User.PrimaryGroup);
                newFile.SetAccessRights(AfpAccessRightsBitmap.OwnerReadWriteExecute);
            }

            //try {
            //    newFile.DateCreated = DateTime.Now;
            //} catch { }
            //try {
            //    newFile.DateModified = DateTime.Now;
            //} catch { }
            //try {
            //    container.DateModified = DateTime.Now;
            //} catch { }

            Log.Add(session, EntryType.Debug, "Session '{0}' created file '{1}'.", session, newFile);

            return AfpResultCode.FPNoErr;
        }

        #endregion
    }
}
